package com.ruoyi.framework.web.service;


import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.*;
import com.ruoyi.common.core.domain.GTPush;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.wx.Jcode2SessionUtil;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.service.impl.SysUserServiceImpl;
import org.apache.http.util.TextUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 微信业务实现类
 */
@Component
public class WeChatService {

    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Value("${weChat.appid}")
    private String appid;

    @Value("${weChat.secret}")
    private String secret;

    @Autowired
    private RedisCache redisUtil;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IAndroidDeviceService androidDeviceService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IWxUserService wxUserService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private IYxUserAndDeviceService yxUserAndDeviceService;

    @Autowired
    private IYxDeviceAndGetuiService yxDeviceAndGetuiService;

    @Autowired
    private IYxAdvertisementService yxAdvertisementService;

    @Autowired
    private IYxUserVipStatusesService yxUserVipStatusesService;

    public R<String> updateNickNameAndAvater(SysUser sysUser) {

        //获取当前登录用户 更新手机号信息
        SysUser user = SecurityUtils.getLoginUser().getUser();

        log.debug( "updateNickNameAndAvater  getUserId ：" + user.getUserId());
        SysUser indb = userService.selectUserById(user.getUserId());
        indb.setAvatar(sysUser.getAvatar());
        indb.setNickName(sysUser.getNickName());
        userService.updateUser(indb);

        if(indb.getAccountType() == 1){
            WxUser query = new WxUser();
            query.setOpenId(indb.getUserName());
            List<WxUser> wxUserList = wxUserService.selectWxUserList(query);
            if(wxUserList != null && wxUserList.size() == 1){
                WxUser wxUserIndb = wxUserList.get(0);
                wxUserIndb.setAvatar(sysUser.getAvatar());
                wxUserIndb.setNickName(sysUser.getNickName());
                wxUserService.updateWxUser(wxUserIndb);
                return R.ok("获取成功");
            }
        }

        return R.fail("获取失败");
    }

    public R<String> bindPhoneNumber(String code) throws Exception{

        //调用微信后台接口获取手机号
        JSONObject sessionInfo = JSONObject.parseObject(getUserPhoneNumber(code));
        String phoneNumber = sessionInfo.getJSONObject("phone_info").getString("phoneNumber");
        if(TextUtils.isEmpty(phoneNumber)){
            return R.fail("获取失败");
        }

        //获取当前登录用户 更新手机号信息
        SysUser user = SecurityUtils.getLoginUser().getUser();

        log.debug( "bindPhoneNumber  userId ：" + user.getUserId());
        SysUser indb = userService.selectUserById(user.getUserId());
        indb.setPhonenumber(phoneNumber);
        userService.updateUser(indb);

        if(indb.getAccountType() == 1){
            WxUser query = new WxUser();
            query.setOpenId(indb.getUserName());
            List<WxUser> wxUserList = wxUserService.selectWxUserList(query);
            if(wxUserList != null && wxUserList.size() == LoginConstants.USER_TYPE_WX){
                WxUser wxUserIndb = wxUserList.get(0);
                wxUserIndb.setPhoneNumber(phoneNumber);
                wxUserService.updateWxUser(wxUserIndb);
                return R.ok("获取成功");
            }
        }

        return R.fail("获取失败");
    }

    public R<String> wxLogin(String code) throws Exception{
        JSONObject sessionInfo = JSONObject.parseObject(jcode2Session(code));

        // 获取用户唯一标识符 openid成功
        String openid = sessionInfo.getString("openid");
        String unionid = sessionInfo.getString("unionid");
        log.debug( "jcode2Session 登录完成 openid ：" + openid + " , unionid:" + unionid);

        if(TextUtils.isEmpty(openid)){
            return R.fail("openid获取失败");

        }
        // 拼接自定义头
        openid = LoginConstants.WX_PREX + openid;
        // 从数据库获取用户信息
        WxUser query = new WxUser();
        query.setOpenId(openid);
        List<WxUser> wxUserList = wxUserService.selectWxUserList(query);

        //首次登录 开始注册
        if(wxUserList == null || wxUserList.size() == 0){

            SysUser sysUser = userService.selectUserByUserName(openid);
            if(sysUser == null){

                // 如何没有历史数据 则 先创建SysUser
                sysUser = new SysUser();
                sysUser.setUserName(openid);
                sysUser.setNickName("测试");
                sysUser.setAccountType(1);
                userService.insertUser(sysUser);
                sysUser = userService.selectUserByUserName(openid);
            }

            //再创建wxuser
            WxUser insertWxUser = new WxUser();
            insertWxUser.setOpenId(openid);
            insertWxUser.setCreateTime(new Date());
            insertWxUser.setUserId(sysUser.getUserId());
            wxUserService.insertWxUser(insertWxUser);


            // 首次注册赠送 3日 会员
            YxUserVipStatuses yxUserSVip = new YxUserVipStatuses();
            yxUserSVip.setVipLevelId(VipConstants.VIP_LEVEL_VIP);
            yxUserSVip.setUserId(sysUser.getUserId());
            yxUserSVip.setExpirationDate(DateUtils.getTimestampByDay(3));
            yxUserVipStatusesService.insertYxUserVipStatuses(yxUserSVip);

            //查询最新的数据
            wxUserList = wxUserService.selectWxUserList(query);

        }


        if(wxUserList != null && wxUserList.size() == LoginConstants.USER_TYPE_WX){
            WxUser wxUser = wxUserList.get(0);
            SysUser sysUser = userService.selectUserById(wxUser.getUserId());

            AsyncManager.me().execute(AsyncFactory.recordLogininfor(sysUser.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
            LoginUser loginUser = createLoginUser(sysUser);
            recordLoginInfo(loginUser.getUserId());
            // 生成token
            String token = tokenService.createToken(loginUser);
            if(TextUtils.isEmpty(wxUser.getPhoneNumber())){
                //  手机号为空 需要去注册
                return R.fail(201,token);
            }else if(TextUtils.isEmpty(wxUser.getAvatar())){
                // 去填写昵称和头像
                return R.fail(202,token);
            }else {
                // 登录成功
                return R.ok(token);
            }

        }


        return R.fail("用户未注册");

    }

    /**
     * @param code
     * @return
     * @throws Exception
     */
    private String jcode2Session(String code)throws Exception{
        String sessionInfo = Jcode2SessionUtil.jscode2session(appid,secret,code,"authorization_code");//登录grantType固定
        return sessionInfo;
    }

    /**
     * @param code
     * @return
     * @throws Exception
     */
    private String getUserPhoneNumber(String code)throws Exception{
        String sessionInfo = Jcode2SessionUtil.getUserPhoneNumber(getAccessToken(),code);//登录grantType固定
        return sessionInfo;
    }

    /**
     * 登录凭证校验
     * @return
     * @throws Exception
     */
    private String getAccessToken() throws Exception{
        //优先从缓存获取 access_token
        String access_token = redisUtil.getCacheObject("wx_access_token");
        if(TextUtils.isEmpty(access_token)){
            //尝试从微信后台获取
            String sessionInfo = Jcode2SessionUtil.getAccessToken(appid,secret);
            JSONObject jsonObject = JSONObject.parseObject(sessionInfo);
            access_token = jsonObject.getString("access_token");
            int expires_in = jsonObject.getInteger("expires_in");
            //存入本地缓存
            redisUtil.setCacheObject("wx_access_token",access_token,expires_in, TimeUnit.SECONDS);
        }

        return access_token;
    }

    public LoginUser createLoginUser(SysUser user)
    {
        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr());
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }

    public R<String> scanBindDevice(String uuid) {

        String deviceId = redisUtil.getCacheObject(CacheConstants.DEVICE_BIND_USER_KEY + uuid);
        // 获取一次立即删除key
        redisUtil.deleteObject(CacheConstants.DEVICE_BIND_USER_KEY + uuid);

        // 检查uuid是否存在
        if(TextUtils.isEmpty(deviceId)){
            return R.fail("设备不存在");
        }
        // 获取 key
        redisUtil.deleteObject(CacheConstants.DEVICE_BIND_USER_KEY + deviceId);

        // 检查 设备信息合法性
        SysUser deviceUser = userService.selectUserByUserName(deviceId);
        if(deviceUser == null || deviceUser.getAccountType() != LoginConstants.USER_TYPE_DEVICE_STU){
            return R.fail("设备信息异常");
        }
        AndroidDevice query = new AndroidDevice();
        query.setDeviceId(deviceId);
        List<AndroidDevice> androidDeviceList = androidDeviceService.selectAndroidDeviceList(query);
        if(androidDeviceList == null || androidDeviceList.size() != 1){
            return R.fail("设备信息异常");
        }


        //获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        log.debug( "scanBindDevice  userid ：" + user.getUserId());
        SysUser indb = userService.selectUserById(user.getUserId());
        if(indb.getAccountType() != LoginConstants.USER_TYPE_WX){
            return R.fail("当前登录信息异常");
        }

        AndroidDevice androidDeviceIndb = androidDeviceList.get(0);

        //开始绑定 设备

        // 1、查询之前是否绑定
        YxUserAndDevice yxUserAndDevice = new YxUserAndDevice();
        yxUserAndDevice.setDeviceId(androidDeviceIndb.getDeviceId());
        yxUserAndDevice.setUserId(indb.getUserId());
        List<YxUserAndDevice> list = yxUserAndDeviceService.selectYxUserAndDeviceList(yxUserAndDevice);
        if(list == null || list.size() > 0){
            return R.fail("该设备已绑定，请勿重复绑定");
        }


        yxUserAndDevice.setCreateTime(new Date());

        // 自动将新绑定的设备 更新为默认设备
        yxUserAndDevice.setIsDefult(DeviceConstants.USER_DEFULT_DEVICE);

        //插入数据
        yxUserAndDeviceService.insertYxUserAndDevice(yxUserAndDevice);

        // 更新 默认设备状态
        YxUserAndDevice queryUser = new YxUserAndDevice();
        queryUser.setUserId(indb.getUserId());
        list = yxUserAndDeviceService.selectYxUserAndDeviceList(queryUser);

        // 自动将新绑定的设备 更新为默认设备 其他设备修改为非默认设备
        if(list != null && list.size() > 1){
            for(YxUserAndDevice yxUserAndDevice1 : list){
                if(!yxUserAndDevice1.getDeviceId().equals(androidDeviceIndb.getDeviceId())){
                    yxUserAndDevice1.setIsDefult(DeviceConstants.USER_NO_DEFULT_DEVICE);
                    yxUserAndDeviceService.updateYxUserAndDevice(yxUserAndDevice1);
                }
            }
        }


        //通知设备 自己已绑定用户
        YxDeviceAndGetui yxDeviceAndGetui = new YxDeviceAndGetui();
        yxDeviceAndGetui.setDeviceId(deviceId);
        List<YxDeviceAndGetui> yxDeviceAndGetuiList = yxDeviceAndGetuiService.selectYxDeviceAndGetuiList(yxDeviceAndGetui);
        if(yxDeviceAndGetuiList != null && yxDeviceAndGetuiList.size() == 1){
            AsyncManager.me().execute(AsyncFactory.transmissionPushByCid(yxDeviceAndGetuiList.get(0).getCid(), GTPush.create(GeTuiPushConstants.QR_CODE_HAS_BINDED)));
        }


        return R.ok("绑定成功");
    }

    public R<List<YxAdvertisement>> advertisementList() {
        YxAdvertisement advertisement = new YxAdvertisement();
        advertisement.setStatus(1l);
        List<YxAdvertisement> list = yxAdvertisementService.selectYxAdvertisementList(advertisement);
        for(YxAdvertisement yxAdvertisement : list){
            yxAdvertisement.setStatus(null);
        }
        return R.ok(list);
    }



    public R<String> bindCid(String cid) throws Exception{

        if(TextUtils.isEmpty(cid)){
            return R.fail("cid 不可为空");
        }
        //获取当前登录用户
        SysUser user = SecurityUtils.getLoginUser().getUser();

        log.debug( "bindCid  userid ：" + user.getUserId());
        SysUser indb = userService.selectUserById(user.getUserId());
        if(indb == null || indb.getAccountType() != LoginConstants.USER_TYPE_WX){
            return R.fail("设备信息异常");
        }

        // 从数据库获取用户信息
        WxUser query = new WxUser();
        query.setOpenId(user.getUserName());
        List<WxUser> wxUserList = wxUserService.selectWxUserList(query);
        if(wxUserList == null || wxUserList.size() != 1){
            return R.fail("微信用户信息异常");
        }

        //查询是否有历史记录
        YxDeviceAndGetui queryGetui = new YxDeviceAndGetui();
        queryGetui.setDeviceId(indb.getUserName());
        List<YxDeviceAndGetui> list = yxDeviceAndGetuiService.selectYxDeviceAndGetuiList(queryGetui);

        if(list != null && list.size() == 1){
            // 更新历史记录
            list.get(0).setCid(cid);
            yxDeviceAndGetuiService.updateYxDeviceAndGetui(list.get(0));
        }else {
            // 插入新记录
            YxDeviceAndGetui yxDeviceAndGetui = new YxDeviceAndGetui();
            yxDeviceAndGetui.setCid(cid);
            yxDeviceAndGetui.setDeviceId(indb.getUserName());
            yxDeviceAndGetuiService.insertYxDeviceAndGetui(yxDeviceAndGetui);
        }

        return R.ok("绑定成功");
    }
}
